﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using FlyingClub.Models;
using FlyingClub.Models.ViewsModels;

namespace FlyingClub.Controllers
{ 
    public class FlightsController : BeforeController
    {
        private FlyingClubDBEntities db = new FlyingClubDBEntities();

        //
        // GET: /Flights/

        public ActionResult Index()
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                var flights = db.Flight.Include("Pilot").Include("Student").Include("Plane").Include("Transaction");

                int id = (int)Session["ID"];
                List<Flight> f = db.Flight.Where(x => x.PilotID == id || x.StudentID == id).OrderByDescending(x => x.DepartureDate).ToList();

                return View(f);
            }
        }

        // 
        // GET: /Flights/List

        public ActionResult List()
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                var flights = db.Flight.Include("Pilot").Include("Student").Include("Plane").Include("Transaction");
                return View(flights.ToList());
            }
        }

        //
        // GET: /Flights/Details/5

        public ActionResult Details(long id)
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                Flight flight = db.Flight.Single(f => f.ID == id);
                return View(flight);
            }
        }

        //
        // GET: /Flights/CreateRegular

        public ActionResult CreateRegular()
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                DropDownLists.Pilots = db.Member.Where(x => x.ID != 1).ToList();

                ViewBag.PlaneID = new SelectList(db.Plane, "ID", "Name");
                ViewBag.TransactionID = new SelectList(db.Transaction, "ID", "Description");
                return View();
            }
        } 

        //
        // POST: /Flights/CreateRegular

        [HttpPost]
        public ActionResult CreateRegular(FlightCreate flightCreate)
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                // Création d'un flight et d'une transaction afin de les rentrer dans la BDD
                Transaction _transaction = new Transaction();
                Flight _flight = new Flight();

                // Création de deux datetime à partir des données du model passée en post
                DateTime _departureDate = new DateTime(flightCreate.DepartureYear, flightCreate.DepartureMonth, flightCreate.DepartureDay, flightCreate.DepartureHour, 0, 0);
                DateTime _arrivalDate = new DateTime(flightCreate.ArrivalYear, flightCreate.ArrivalMonth, flightCreate.ArrivalDay, flightCreate.ArrivalHour, 0, 0);

                // Calcul de l'hourRate et récupération du wallet du pilote
                int _hourRate = db.Plane.First(x => x.ID == flightCreate.PlaneID).HourRate * Math.Abs(flightCreate.DepartureHour - flightCreate.ArrivalHour);
                int _wallet = db.Member.First(x => x.ID == flightCreate.PilotID).Wallet;

                // Si le pilote a assez de sous et si la de départ est supérieure à maintenant et si la date d'arrivée est supérieure à la date de départe et si le vol dure moins de 9h et si le pilote et l'avion sont disponibles, alors c'est bon.
                if (_hourRate < _wallet)
                {
                    if (_departureDate > DateTime.Now && _departureDate < _arrivalDate && flightCreate.ArrivalHour - flightCreate.DepartureHour < 9)
                    {
                        if (this.MemberIsAvailable(flightCreate.PilotID, _departureDate) && this.MemberIsAvailable(flightCreate.PilotID, _arrivalDate))
                        {
                            if (this.PlaneIsAvailable(flightCreate.PlaneID, _departureDate) && this.PlaneIsAvailable(flightCreate.PlaneID, _arrivalDate))
                            {
                                // Remplissage des données de transaction
                                _transaction.Payload = db.Plane.First(x => x.ID == flightCreate.PlaneID).HourRate;
                                _transaction.CreditID = db.Member.First(x => x.ID == 1).ID;
                                _transaction.DebtorID = flightCreate.PilotID;
                                _transaction.Date = DateTime.Now;
                                _transaction.Description = "Regular Flight : " + flightCreate.PilotID + ", " + DateTime.Now.ToString();

                                if (ModelState.IsValid)
                                {
                                    // Ajout de la transaction à la BDD pour pouvoir la récupérer plus tard pour le flight
                                    db.Transaction.AddObject(_transaction);
                                    db.SaveChanges();

                                    // Remplissage des données du flight
                                    _flight.DepartureAirfield = flightCreate.DepartureAirfield;
                                    _flight.DepartureDate = _departureDate;
                                    _flight.ArrivalAirfield = flightCreate.ArrivalAirfield;
                                    _flight.ArrivalDate = _arrivalDate;

                                    if (Session["Staff"].Equals(true))
                                        _flight.PilotID = flightCreate.PilotID;
                                    else
                                        _flight.PilotID = (int)Session["ID"];

                                    _flight.StudentID = null;
                                    _flight.PlaneID = flightCreate.PlaneID;
                                    _flight.TransactionID = db.Transaction.OrderByDescending(x => x.ID).First().ID;
                                    _flight.Validate = true;

                                    db.Flight.AddObject(_flight);

                                    // MAJ des données du wallet et du pilote
                                    Member __wallet = db.Member.Single(x => x.ID == 1);
                                    __wallet.Wallet += _hourRate;

                                    Member _pilot = db.Member.Single(x => x.ID == _flight.PilotID);
                                    _pilot.Wallet -= _hourRate;

                                    db.SaveChanges();

                                    return RedirectToAction("Index");
                                }
                            }
                            else
                                ViewBag.ErrorMessage = "L'avion n'est pas disponible pour cette plage horaire.";
                        }
                        else
                            ViewBag.ErrorMessage = "Le pilote n'est pas disponible pour cette plage horaire.";
                    }
                    else
                        ViewBag.ErrorMessage = "Les dates ne sont pas conformes. Vérifiez que la date de départ ne soit pas révolue, la durée du vol (8h max) ainsi que la date de départ soit bien inférieure à la date d'arrivée.";
                }
                else
                    ViewBag.ErrorMessage = "Le porte-monnaie n'est pas suffisamment fourni pour ce vol.";

                ViewBag.PilotID = new SelectList(db.Member, "ID", "Lastname", flightCreate.PilotID);
                ViewBag.PlaneID = new SelectList(db.Plane, "ID", "Name", flightCreate.PlaneID);
                ViewBag.TransactionID = new SelectList(db.Transaction, "ID", "Description", _flight.TransactionID);
                return View(flightCreate);   
            }
        }

        //
        // GET: /Flights/CreateSchool

        public ActionResult CreateSchool()
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                DropDownLists.Pilots = db.Member.Where(x => x.ID != 1 && x.InstructorNumber != 0).ToList();
                DropDownLists.Students = db.Member.Where(x => x.ID != 1 && x.InstructorNumber == 0).ToList();

                ViewBag.PlaneID = new SelectList(db.Plane, "ID", "Name");
                ViewBag.TransactionID = new SelectList(db.Transaction, "ID", "Description");
                return View();
            }
        }

        //
        // POST: /Flights/CreateSchool

        [HttpPost]
        public ActionResult CreateSchool(FlightCreate flightCreate)
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                // Création d'un flight et d'une transaction afin de les rentrer dans la BDD
                Transaction _transaction = new Transaction();
                Flight _flight = new Flight();

                // Création de deux datetime à partir des données du model passée en post
                DateTime _departureDate = new DateTime(flightCreate.DepartureYear, flightCreate.DepartureMonth, flightCreate.DepartureDay, flightCreate.DepartureHour, 0, 0);
                DateTime _arrivalDate = new DateTime(flightCreate.ArrivalYear, flightCreate.ArrivalMonth, flightCreate.ArrivalDay, flightCreate.ArrivalHour, 0, 0);

                // Calcul de l'hourRate et récupération du wallet du pilote
                int _hourRate = (db.Plane.Single(x => x.ID == flightCreate.PlaneID).HourRate + 20) * Math.Abs(flightCreate.DepartureHour - flightCreate.ArrivalHour);
                int _wallet = db.Member.Single(x => x.ID == flightCreate.StudentID).Wallet;

                // Si le pilote a assez de sous et si la de départ est supérieure à maintenant et si la date d'arrivée est supérieure à la date de départe et si le vol dure moins de 9h, alors c'est bon.
                if (_hourRate < _wallet)
                {
                    if (_departureDate > DateTime.Now && _departureDate < _arrivalDate && flightCreate.ArrivalHour - flightCreate.DepartureHour < 9)
                    {
                        if (this.MemberIsAvailable(flightCreate.PilotID, _departureDate) && this.MemberIsAvailable(flightCreate.PilotID, _arrivalDate))
                        {
                            if (this.PlaneIsAvailable(flightCreate.PlaneID, _departureDate) && this.PlaneIsAvailable(flightCreate.PlaneID, _arrivalDate))
                            {
                                // Remplissage des données de transaction
                                _transaction.Payload = db.Plane.Single(x => x.ID == flightCreate.PlaneID).HourRate;
                                _transaction.CreditID = db.Member.Single(x => x.ID == 1).ID;
                                _transaction.DebtorID = flightCreate.StudentID;
                                _transaction.Date = DateTime.Now;
                                _transaction.Description = "Regular School : " + flightCreate.PilotID + " with student " + flightCreate.StudentID + ", " + DateTime.Now.ToString();

                                if (ModelState.IsValid)
                                {
                                    // Ajout de la transaction à la BDD pour pouvoir la récupérer plus tard pour le flight
                                    db.Transaction.AddObject(_transaction);
                                    db.SaveChanges();

                                    // Remplissage des données du flight
                                    _flight.DepartureAirfield = flightCreate.DepartureAirfield;
                                    _flight.DepartureDate = _departureDate;
                                    _flight.ArrivalAirfield = flightCreate.ArrivalAirfield;
                                    _flight.ArrivalDate = _arrivalDate;
                                    _flight.PilotID = flightCreate.PilotID;
                                    if (Session["Staff"] != null)
                                        _flight.StudentID = flightCreate.StudentID;
                                    else
                                        _flight.StudentID = (int)Session["ID"];
                                    _flight.PlaneID = flightCreate.PlaneID;
                                    _flight.TransactionID = db.Transaction.OrderByDescending(x => x.ID).First().ID;
                                    _flight.Validate = false;

                                    db.Flight.AddObject(_flight);

                                    // MAJ du wallet, du pilote et du student
                                    Member __wallet = db.Member.Single(x => x.ID == 1);
                                    __wallet.Wallet += db.Plane.Single(x => x.ID == flightCreate.PlaneID).HourRate * Math.Abs(flightCreate.DepartureHour - flightCreate.ArrivalHour);

                                    Member _pilot = db.Member.Single(x => x.ID == _flight.PilotID);
                                    _pilot.Wallet += 20 * Math.Abs(flightCreate.DepartureHour - flightCreate.ArrivalHour);

                                    Member _student = db.Member.Single(x => x.ID == _flight.StudentID);
                                    _student.Wallet -= _hourRate;

                                    // Création d'une nouvelle transaction pour le pilote
                                    _transaction = new Transaction();
                                    _transaction.Payload = db.Plane.Single(x => x.ID == flightCreate.PlaneID).HourRate;
                                    _transaction.CreditID = db.Member.Single(x => x.ID == flightCreate.PilotID).ID;
                                    _transaction.DebtorID = flightCreate.StudentID;
                                    _transaction.Date = DateTime.Now;
                                    _transaction.Description = "Regular School : " + flightCreate.PilotID + " with student " + flightCreate.StudentID + ", " + DateTime.Now.ToString();

                                    db.Transaction.AddObject(_transaction);

                                    db.SaveChanges();

                                    // Notification du pilote
                                    this.SendEmail(_pilot.Email, "Vous avez un vol en attente de validation !" ,  "Veuillez cliquer ici pour valider votre vol : http://flyingclub.com/Flights/ValidateFlight/" + db.Flight.OrderByDescending(x => x.ID).First());

                                    return RedirectToAction("Index");
                                }
                            }
                            else
                                ViewBag.ErrorMessage = "L'avion n'est pas disponible pour cette plage horaire.";
                        }
                        else
                            ViewBag.ErrorMessage = "Le pilote n'est pas disponible pour cette plage horaire.";
                    }
                    else
                        ViewBag.ErrorMessage = "Les dates ne sont pas conformes. Vérifiez la durée du vol (8h max) ainsi que la date de départ soit bien inférieure à la date d'arrivée.";
                }
                else
                    ViewBag.ErrorMessage = "Le porte-monnaie n'est pas suffisamment fourni pour ce vol.";

                ViewBag.PilotID = new SelectList(db.Member, "ID", "Lastname", flightCreate.PilotID);
                ViewBag.StudentID = new SelectList(db.Member, "ID", "Lastname", flightCreate.StudentID);
                ViewBag.PlaneID = new SelectList(db.Plane, "ID", "Name", flightCreate.PlaneID);
                ViewBag.TransactionID = new SelectList(db.Transaction, "ID", "Description", _flight.TransactionID);
                return View(flightCreate);
            }
        }
        
        //
        // GET: /Flights/Edit/5
 
        public ActionResult Edit(long id)
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                Flight flight = db.Flight.Single(f => f.ID == id);
                ViewBag.PilotID = new SelectList(db.Member, "ID", "Firstname", flight.PilotID);
                ViewBag.StudentID = new SelectList(db.Member, "ID", "Firstname", flight.StudentID);
                ViewBag.PlaneID = new SelectList(db.Plane, "ID", "Name", flight.PlaneID);
                ViewBag.TransactionID = new SelectList(db.Transaction, "ID", "Description", flight.TransactionID);
                return View(flight);
            }
        }

        //
        // POST: /Flights/Edit/5

        [HttpPost]
        public ActionResult Edit(Flight flight)
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                if (ModelState.IsValid)
                {
                    db.Flight.Attach(flight);
                    db.ObjectStateManager.ChangeObjectState(flight, EntityState.Modified);
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
                ViewBag.PilotID = new SelectList(db.Member, "ID", "Firstname", flight.PilotID);
                ViewBag.StudentID = new SelectList(db.Member, "ID", "Firstname", flight.StudentID);
                ViewBag.PlaneID = new SelectList(db.Plane, "ID", "Name", flight.PlaneID);
                ViewBag.TransactionID = new SelectList(db.Transaction, "ID", "Description", flight.TransactionID);
                return View(flight);
            }
        }

        //
        // GET: /Flights/Delete/5
 
        public ActionResult Delete(long id)
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                Flight flight = db.Flight.Single(f => f.ID == id);
                return View(flight);
            }
        }

        //
        // POST: /Flights/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(long id)
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                Flight flight = db.Flight.Single(f => f.ID == id);
                db.Flight.DeleteObject(flight);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
        }

        //
        // GET: /Flights/Validate

        public ActionResult Validate()
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                int pilotID = (int)Session["ID"];
                List<Flight> flights = db.Flight.Where(x => (x.Validate == null || x.Validate == false) && x.PilotID == pilotID).ToList();
                return View(flights);
            }
        }

        //
        // GET: /Flights/ValidateFlight/5

        public ActionResult ValidateFlight(int id)
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                Flight flight = db.Flight.Single(x => x.ID == id);
                flight.Validate = true;
                db.SaveChanges();

                return View(flight);
            }
        }


        // 
        // POST: /Flights/ValidateFlight/5

        [HttpPost]
        public ActionResult ValidateFlight(Flight flight)
        {
            int _access = this.GetAccess();

            if (_access == 0)
                return RedirectToAction("LogOn", "Members");
            else
            {
                flight.Validate = true;
                db.Flight.Attach(flight);
                db.ObjectStateManager.ChangeObjectState(flight, EntityState.Modified);
                db.SaveChanges();

                int memberID = (int)Session["ID"];
                Session["NbToValidate"] = db.Flight.Count(x => x.PilotID == memberID && x.DepartureDate >= DateTime.Now && (x.Validate == false || x.Validate == null));

                return RedirectToAction("Validate", "Flights");
            }
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}